home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / v16pcx.zip / V16PCX.C next >
C/C++ Source or Header  |  1993-05-20  |  7KB  |  336 lines

  1. #include "stdio.h"
  2. #include "process.h"
  3. #include "conio.h"
  4. #include "alloc.h"
  5. #include "dos.h"
  6. #include "graphics.h"
  7. #include "mem.h"
  8.  
  9. #define VGA   0x0012
  10. #define STRIPSIZE 24
  11. #define pixels2bytes(n)  ((n+7)/8)
  12.  
  13. typedef struct {
  14.                 char manufacturer;
  15.                 char version;
  16.                 char encoding;
  17.                 char bits_per_pixel;
  18.                 int xmin,ymin;
  19.                 int xmax,ymax;
  20.                 int hres;
  21.                 int vres;
  22.                 char palette[48];
  23.                 char reserved;
  24.                 char colour_planes;
  25.                 int bytes_per_line;
  26.                 int palette_type;
  27.                 char filler[58];
  28.                 } PCXHEAD;
  29.  
  30. ShowPicture(char *p,int width,int depth,int mode,char *palette);
  31. char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  32. char bittable[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  33. unsigned int screenwide,screendeep,screenbytes;
  34. char *screentable[800];
  35. char *farPtr(char *p,long l);
  36.  
  37. error(char *s);
  38. UnpackPcxFile(char *p,FILE *fp,int width,int depth,int bytes,int bits,
  39.  int winflag);
  40. void init(int mode,char *p);
  41. void deinit(void);
  42. setvgapalette(char *p);
  43. ReadPcxLine(char *p,FILE *fp,int bytes);
  44. egaplane(int n);
  45.  
  46. main(int argc,char *argv[])
  47.  
  48.      {
  49.      PCXHEAD header;
  50.      FILE *fp;
  51.      char *p;
  52.      int width,depth,bytes,bits,winflag,planesize,n=VGA;
  53.  
  54.      /* check for arguments */
  55.      if(argc<=1) error("I need a path to a PCX file");
  56.  
  57.      /* attempt to open the file */
  58.      if((fp=fopen(argv[1],"rb")) == NULL)
  59.          error("Error opening the file");
  60.  
  61.      /* read in the header */
  62.      if(fread((char *)&header,1,sizeof(PCXHEAD),fp) != sizeof(PCXHEAD))
  63.          error("Error reading the PCX header");
  64.  
  65.      /* check to make sure it's a picture */
  66.      if(header.manufacturer != 0x0a)
  67.          error("This is not a PCX file");
  68.  
  69.      /* allocate a big buffer */
  70.      width = (header.xmax-header.xmin)+1;
  71.      depth = (header.ymax-header.ymin)+1;
  72.      bytes=header.bytes_per_line;
  73.  
  74.          if(header.bits_per_pixel == 1) bits=header.colour_planes;
  75.          else bits=header.bits_per_pixel;
  76.  
  77.          if(header.bits_per_pixel==4 && header.colour_planes==1)
  78.          {winflag=1;planesize=1;}
  79.          else {winflag=0;planesize=4;}
  80.  
  81.          if(bits < 2 || bits > 4)
  82.              error("This file has the wrong number of colours");
  83.  
  84.          if((p=(char *)farmalloc((long)bytes*(long)planesize*(long)depth)) == NULL)
  85.              error("Can't allocate memory");
  86.          puts("Unpacking file");
  87.          /* unpack the file */
  88.          if(UnpackPcxFile(p,fp,width,depth,bytes,bits,winflag))
  89.              error("Error unpacking the file");
  90.          puts("Showing picture");
  91.          ShowPicture(p,width,depth,n,header.palette);
  92.  
  93.          free(p);
  94.          fclose(fp);
  95.  
  96. return(0);
  97. }
  98.  
  99. ShowPicture(char *p,int width,int depth,int mode,char *palette)
  100. {
  101.     char *pr;
  102.     unsigned int i,w,bytes,linebytes;
  103.  
  104.     init(mode,palette);
  105.  
  106.     bytes=pixels2bytes(width);
  107.     linebytes=bytes<<2;
  108.  
  109.     if(width>screenwide) w=pixels2bytes(screenwide);
  110.     else w=pixels2bytes(width);
  111.  
  112.     for(i=0;i<screendeep;++i) {
  113.         if(i>=depth) break;
  114.         pr=farPtr(p,(long)i*(long)linebytes);
  115.  
  116.         egaplane(1);
  117.         memcpy(screentable[i],pr,w);
  118.         pr+=bytes;
  119.  
  120.         egaplane(2);
  121.         memcpy(screentable[i],pr,w);
  122.         pr+=bytes;
  123.  
  124.         egaplane(4);
  125.         memcpy(screentable[i],pr,w);
  126.         pr+=bytes;
  127.  
  128.         egaplane(8);
  129.         memcpy(screentable[i],pr,w);
  130.         pr+=bytes;
  131.  
  132.         egaplane(15);
  133.  
  134.         }
  135.         getch();
  136.         deinit();
  137.         return(0);
  138.         }
  139.  
  140.  
  141.  
  142.  
  143.  
  144. /* unpack and display a PCX file... dealing with all the weird ones */
  145. UnpackPcxFile(char *p,FILE *fp,int width,int depth,int bytes,int bits,
  146.  int winflag)
  147. {
  148.          char *lb,*eb,*pr;
  149.          int c,i,k,j,x,linebytes;
  150.  
  151.          /* it's nybbbled, one line is half the width */
  152.          if(winflag) {
  153.                  linebytes=bytes;
  154.                  bytes=pixels2bytes(width);
  155.          } else linebytes=bytes*bits;
  156.  
  157.          /*allocate some scratch buffers */
  158.          if((lb=(char *)malloc(bytes<<2)) == NULL) return(1);
  159.  
  160.          if((eb=(char *)malloc(bytes<<2)) == NULL) {
  161.                  free(lb);
  162.                  return(1);
  163.          }
  164.  
  165.          /* loop through all the strips */
  166.          for(i=0;i<depth;++i) {
  167.  
  168.          /* fetch a line */
  169.          memset(lb,0,bytes<<2);
  170.          if(ReadPcxLine(lb,fp,linebytes)!=linebytes) {
  171.             deinit();
  172.             free(eb);
  173.             free(lb);
  174.             return(1);
  175.          }
  176.  
  177.                          /* if it's nybbled, rework it as planes */
  178.                          if(winflag) {
  179.                                 memcpy(eb,lb,linebytes);
  180.                                 memset(lb,0,linebytes);
  181.                                 for(j=x=0;j<width;) {
  182.                                      c=eb[x] >> 4;
  183.                                      pr=lb;
  184.                                          for(k=0;k<bits;++k) {
  185.                                              if(c & bittable[k])
  186.                                                  pr[j>>3] |= masktable[j & 0x0007];
  187.                                             else
  188.                                                  pr[j>>3] &= ~masktable[j & 0x0007];
  189.                                             pr+=bytes;
  190.                                      }
  191.                                      ++j;
  192.                                      c=eb[x];
  193.                                      pr=lb;
  194.                                      for(k=0;k<bits;++k) {
  195.                                             if(c & bittable[k])
  196.                                                 pr[j>>3] |= masktable[j & 0x0007];
  197.                                             else
  198.                                                 pr[j>>3] &= ~masktable[j & 0x0007];
  199.                                             pr+=bytes;
  200.                                      }
  201.                                      ++j;
  202.                                      ++x;
  203.                                 }
  204.                          }
  205.                          /* copy the planes into the strip buffer */
  206.                          x=0;
  207.                          for(j=0;j<4;++j) {
  208.                                 memcpy(p+pixels2bytes(width)*j,
  209.                                     lb+x,pixels2bytes(width));
  210.                                 x+=bytes;
  211.                          }
  212.                          p=farPtr(p,(long)(pixels2bytes(width)<<2));
  213.                  }
  214.  free(eb);
  215.  free(lb);
  216.  return(0);
  217. }
  218.  
  219.         /* read and decode a PCX line into p */
  220.      ReadPcxLine(char *p,FILE *fp,int bytes)
  221.      {
  222.             int n=0,c,i;
  223.  
  224.             /* null the buffer */
  225.             memset(p,0,bytes);
  226.             do {
  227.                     /* get a key byte */
  228.                     c=fgetc(fp) & 0xff;
  229.                     /* if it's a run of bytes field */
  230.                     if((c & 0xc0) == 0xc0) {
  231.                          /* and off the high bits */
  232.                          i=c & 0x3f;
  233.                          /* get the run byte */
  234.                          c=fgetc(fp);
  235.                          /* run the byte */
  236.                          while(i--) p[n++]=c;
  237.                     }
  238.                     /* else just store it */
  239.                         else p[n++]=c;
  240.                     } while(n < bytes);
  241.                     return(n);
  242.             }
  243.  
  244.             void init(int mode,char *palette)
  245.             /* turn on graphics mode */
  246.  
  247.             {
  248.              union REGS r;
  249.              int i;
  250.  
  251.              screenwide=640;
  252.              screendeep=480;
  253.              screenbytes=80;
  254.              for(i=0;i<screendeep;++i)
  255.                 screentable[i]=(char *)MK_FP(0xa000,i*screenbytes);
  256.              r.x.ax=mode;
  257.              int86(0x10,&r,&r);
  258.              setvgapalette(palette);
  259.      }
  260.  
  261.      void deinit(void)  /* turn off graphics card */
  262.      {
  263.             union REGS r;
  264.  
  265.             r.x.ax=0x0003;
  266.             int86(0x10,&r,&r);
  267.         }
  268.  
  269.  
  270.      /*set the EGA palette to RGB buffer p */
  271.      setvgapalette(char *p)
  272.      {
  273.  
  274.          union REGS r;
  275.          int i;
  276.  
  277.          for(i=0;i<16;++i) {
  278.          r.h.dh=(*p++)>>2;
  279.          r.h.ch=(*p++)>>2;
  280.          r.h.cl=(*p++)>>2;
  281.          r.x.ax=0x1010;
  282.          r.x.bx=i;
  283.          int86(0x10,&r,&r);
  284.      }
  285.      r.x.bx=0;
  286.      for(i=0;i<16;++i) {
  287.      r.x.ax=0x1000;
  288.      int86(0x10,&r,&r);
  289.      r.x.bx+=0x0101;
  290.      }
  291.  
  292.      return(0);
  293. }
  294.  
  295.  
  296.      error(char *s)
  297.      {
  298.          puts(s);
  299.          exit(1);
  300.          return(0);
  301.      }
  302.  
  303.  char *farPtr(char *p,long l) /* Return a far pointer p + l */
  304. {
  305.  unsigned int seg,off;
  306.  
  307.  seg = FP_SEG(p);
  308.  off = FP_OFF(p);
  309.  seg += (off/16);
  310.  off &= 0x000f;
  311.  off += (unsigned int)(l & 0x000fL);
  312.  seg += (l/16L);
  313.  p=(char *)MK_FP(seg,off);
  314.  return(p);
  315. }
  316.  
  317. egaplane(int n) /* set the current display plane */
  318. {
  319.  outportb(0x3c4,0x02);
  320.  outportb(0x3c5,n);
  321.  return(0);
  322. }
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.